package com.sky.business.sys.handler.cmcc;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sky.business.sys.domain.CameraConfig;
import com.sky.business.sys.domain.SystemConfig;
import com.sky.business.sys.domain.TrackTask;
import com.sky.business.sys.event.CmccEndTrackingEvent;
import com.sky.business.sys.event.CmccEndTrackingReportEvent;
import com.sky.business.sys.event.EdgeEndTrackingEvent;
import com.sky.business.sys.handler.MqttEventHandler;
import com.sky.business.sys.service.CameraConfigService;
import com.sky.business.sys.service.SystemConfigService;
import com.sky.business.sys.service.TrackTaskService;
import com.sky.business.sys.util.MQTTClientUtils;
import com.sky.common.config.CacheConstants;
import com.sky.common.enums.TrackStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 移动凌云平台开始跟踪任务处理器
 *
 */
@Slf4j
@Component
public class CmccEndTrackingEventHandler implements MqttEventHandler {

    public static ObjectMapper objectMapper = new ObjectMapper().setTimeZone(SimpleTimeZone.getTimeZone("GMT+8"));

    @Autowired
    private TrackTaskService trackTaskService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private CameraConfigService cameraConfigService;

    @Override
    public boolean match(String topic, String msg, String event) {
        return "EndTracking".equals(event);
    }


    /**
     * 处理单个设备结束任务
     * @param taskId 任务id
     * @param deviceIdList 设备id列表
     */
    public void endTrackingWithDeviceId(String taskId, List<String> deviceIdList)  {
        SystemConfig systemConfig = systemConfigService.getSystemConfig();
        List<CameraConfig> cameraConfigList = cameraConfigService.findByDeviceIdIn(deviceIdList);
        Map<String,CameraConfig> cameraConfigMap = cameraConfigList.stream().collect(Collectors.toMap(k->k.getCameraDeviceId(),v->v));
        for(String deviceId:deviceIdList) {
            try {
                //查询设备是否存在
                CameraConfig cameraConfig = cameraConfigMap.get(deviceId);
                if (cameraConfig == null) {
                    //通知凌云平台设备不存在
                    CmccEndTrackingReportEvent cmccEndTrackingReportEvent = new CmccEndTrackingReportEvent(systemConfig.getEdgeId(), deviceId, taskId, 0, CacheConstants.CODE_STATUS_ERROR, "设备不存在", null);
                    String responseMsg = objectMapper.writeValueAsString(cmccEndTrackingReportEvent);
                    MQTTClientUtils.publish(MQTTClientUtils.CMCC_MQTT_CLIENT, systemConfig.getCmccReportingTopic(), CacheConstants.DEFAULT_QOS, responseMsg);
                } else {
                    trackTaskService.endTrackByTaskIdAndDeviceId(taskId, deviceId, new Date());
                    EdgeEndTrackingEvent edgeEndTrackingEvent = new EdgeEndTrackingEvent(systemConfig.getEdgeId(), deviceId, taskId);
                    String edgeEndTrackingMsg = objectMapper.writeValueAsString(edgeEndTrackingEvent);
                    MQTTClientUtils.publish(MQTTClientUtils.LOCAL_MQTT_CLIENT, cameraConfig.getDispatcherTopic(), CacheConstants.DEFAULT_QOS, edgeEndTrackingMsg);
                }
            }catch (Exception e){
                log.error("停止追踪任务发生异常,任务ID:{}, 设备ID:{}",taskId,deviceId,e);
            }
        }
    }

    /**
     * 停止追踪任务对应的所有设备
     * @param taskId 任务id
     */
    public void endTrackingForAllDevice(String taskId){
        SystemConfig systemConfig = systemConfigService.getSystemConfig();
        Date now = new Date();
        List<TrackTask> trackTaskList = trackTaskService.findByTaskIdAndStatus(taskId, TrackStatus.TRACKING);
        if (trackTaskList.size() > 0) {
            Set<String> deviceIdSet = new HashSet<>();
            for (TrackTask trackTask : trackTaskList) {
                trackTaskService.endTrack(trackTask,now);
                deviceIdSet.add(trackTask.getDeviceId());
            }
            List<CameraConfig> cameraConfigList = cameraConfigService.findByDeviceIdIn(new ArrayList<>(deviceIdSet));
            Map<String,CameraConfig> cameraConfigMap = cameraConfigList.stream().collect(Collectors.toMap(k->k.getCameraDeviceId(),v->v));
            for(String currDeviceId:deviceIdSet){
                //转发给终端
                try {
                    CameraConfig cameraConfig = cameraConfigMap.get(currDeviceId);
                    if (cameraConfig != null) {
                        EdgeEndTrackingEvent edgeEndTrackingEvent = new EdgeEndTrackingEvent(systemConfig.getEdgeId(),currDeviceId,taskId);
                        String edgeEndTrackMsg = objectMapper.writeValueAsString(edgeEndTrackingEvent);
                        MQTTClientUtils.publish(MQTTClientUtils.LOCAL_MQTT_CLIENT, cameraConfig.getDispatcherTopic(), CacheConstants.DEFAULT_QOS, edgeEndTrackMsg);
                    } else {
                        log.error("设备不存在,设备ID:{}", currDeviceId);
                    }
                }catch (Exception e){
                    log.error("发送结束任务消息异常,任务ID:{}, 设备ID:{}",taskId,currDeviceId,e);
                }
            }
        }else{
            log.error("cmcc停止追踪任务不存在, 任务ID:{}",taskId);
        }
    }

    @Override
    public void handle(String topic, String msg) throws Exception {
        CmccEndTrackingEvent cmccEndTrackingEvent = objectMapper.readValue(msg, CmccEndTrackingEvent.class);
        CmccEndTrackingEvent.Metadata metadata = cmccEndTrackingEvent.getMetadata();
        String taskId = metadata.getTaskId();
        List<String> deviceIdList = metadata.getDeviceIds();
        if (deviceIdList == null || deviceIdList.isEmpty()) {
            //没有指定设备,全部停止
            endTrackingForAllDevice(taskId);
        } else {
            //指定设备,指停止单个设备
            endTrackingWithDeviceId(taskId,deviceIdList);
        }
    }
}
